import os
import time
import json
import requests
from loguru import logger
from configparser import ConfigParser
import datetime
from .my_logger import Loggers


class FeishuBiTable:

    def __init__(self, app_config: dict, app_token: str):
        # todo 后续加个level
        self.logger = Loggers(level='DEBUG').logger
        self.tenant_access_token: str = ''
        self.app_config = app_config
        self.app_token = app_token
        self.headers = {
            'Authorization': f'Bearer {self.get_tenant_access_token()}',
            'Content-Type': 'application/json'}

    def get_tenant_access_token(self):
        config = ConfigParser()
        path = os.path.join(os.path.dirname(__file__), 'feishu_auth.ini')
        config.read(path)

        # 从 app_config 获取相关信息
        section_name = self.app_config.get('name')
        app_id = self.app_config.get('app_id')
        app_secret = self.app_config.get('app_secret')

        if section_name not in config:
            config.add_section(section_name)
            config.set(section_name, 'value', '')
            config.set(section_name, 'created_timestamp', '')
            config.set(section_name, 'created_time', '')
            with open(path, 'w') as f:
                config.write(f)

        created_time = config.get(section_name, 'created_timestamp', fallback=None)
        # 该token有效期为2hours，剩下0.5hours才支持刷新，即是重新获取,这里设置超过5400秒后再去获取
        if not created_time or int(time.time()) - int(created_time) > 1000:
            url = 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal'
            payload = json.dumps({'app_id': app_id, 'app_secret': app_secret})
            headers = {'Content-Type': 'application/json'}
            response = requests.post(url, headers=headers, data=payload)

            if response.status_code != 200:
                self.logger.debug(f'get_tenant_access_token fail: {response.text}, status code: {response.status_code}')
                return

            data = response.json()
            tenant_access_token = data.get('tenant_access_token')
            config.set(section_name, 'value', tenant_access_token)
            config.set(section_name, 'created_timestamp', str(int(time.time())))
            config.set(section_name, 'created_time', str(datetime.datetime.now()))

            with open(path, 'w') as f:
                config.write(f)
            self.logger.debug(f'app:{section_name}, get_tenant_access_token success and set ini file: {data}')
            return tenant_access_token

        return config.get(section_name, 'value')

    def create_bitable(self, bitable_name):
        """
        :param bitable_name: 多维表格名
        """
        url = "https://open.feishu.cn/open-apis/bitable/v1/apps"
        payload = json.dumps({
            "name": bitable_name
        })
        response = requests.post(url, headers=self.headers, data=payload)

        if response.status_code != 200:
            logger.error(f'create bitable fail: {response.text}, status code: {response.status_code}')
            return
        data = response.json()
        logger.debug(f'create bitable success: {data}')
        return data

    def get_tables(self):
        # 获取数据表
        try:
            url = f'https://open.feishu.cn/open-apis/bitable/v1/apps/{self.app_token}/tables?page_size=400'
            response = requests.get(url, headers=self.headers, data='')
            data = response.json()
            if response.status_code == 200 and data.get('msg') == 'success':
                self.logger.debug(f'get_tables success: {data}, status code: {response.status_code}')
                tables_info = data.get('data').get('items')
                return tables_info
            else:
                # self.logger.error(f'get tables fail: {response.text}')
                return []
        except Exception as e:
            logger.exception(e)

    def create_table(self, table_id=None, table_name=None, view_name: str = None, fields: list = None):
        """
        :param table_id: 数据表名
        :param table_name: 数据表ID
        :param view_name: 视图名
        :param fields: 表字段 格式：[{'field_name': value, 'type': 1}]
        :return: table_id
        """
        print('create_table:!!!!', table_id, table_name, view_name, fields)
        try:
            #  先判断是否已经存在数据表
            tables_info = self.get_tables()
            if table_name:
                table_id = next((info.get('table_id') for info in tables_info if info.get('name') == table_name), None)
                if table_id:
                    self.logger.debug(f'数据表:{table_name} 已经存在, table_id: {table_id}')
                    return table_id

            if table_id:
                table_id, table_name = next(((info.get('table_id'), info.get('name')) for info in tables_info if
                                             info.get('table_id') == table_id), None)
                if table_id:
                    self.logger.debug(f'数据表:{table_name} 已经存在, table_id: {table_id}')
                    return table_id

            url = f"https://open.feishu.cn/open-apis/bitable/v1/apps/{self.app_token}/tables"
            payload = json.dumps({
                "table": {
                    "default_view_name": view_name,
                    "fields": fields,
                    "name": table_name
                }
            })
            #
            # print({
            #     "table": {
            #         "default_view_name": view_name,
            #         "fields": fields,
            #         "name": table_name
            #     }
            # })
            # time.sleep(11111)
            response = requests.post(url, headers=self.headers, data=payload)
            if response.status_code != 200:
                self.logger.error(f'create_table fail: {response.text}, status code: {response.status_code}')
                return
            data = response.json()
            self.logger.debug(f'create table success: {data}')
            table_id = data.get('data').get('table_id')
            return table_id

        except Exception as e:
            self.logger.exception(e)

    def add_table_field(self, table_id, field_info: dict):
        """
        :param table_id:
        :param field_info: {"field_name": field_name, "type": type, "property": property}
        :return:
        """
        try:
            url = f'https://open.feishu.cn/open-apis/bitable/v1/apps/{self.app_token}/tables/{table_id}/fields'
            payload = json.dumps(field_info)
            response = requests.request("POST", url, headers=self.headers, data=payload)
            data = response.json()
            if response.status_code != 200:
                logger.error(f'add table field fail: {data}, status code: {response.status_code}')
                return
            logger.debug(f'add table field success: {data}')
            return data

        except Exception as e:
            logger.exception(e)

    def add_view(self, table_id, view_name):
        url = f"https://open.feishu.cn/open-apis/bitable/v1/apps/{self.app_token}/tables/{table_id}/views"
        payload = json.dumps({'view_name': view_name})
        response = requests.post(url, headers=self.headers, data=payload)
        if response.status_code != 200:
            logger.error(f'add view fail: {response.text}, status code: {response.status_code}')
        data = response.json()
        logger.debug(f'add view success: {data}')
        return data

    def update_view(self, table_id, view_id, payload: dict):
        url = f"https://open.feishu.cn/open-apis/bitable/v1/apps/{self.app_token}/tables/{table_id}/views/{view_id}"
        payload = payload

        print(json.dumps(payload))
        # time.sleep(11111)
        response = requests.patch(url, headers=self.headers, json=payload)
        print(response.status_code)
        print(response.json())
        # if response.status_code != 200:
        #     logger.error(f'add view fail: {response.text}, status code: {response.status_code}')
        # data = response.json()
        # logger.debug(f'add view success: {data}')
        # return data

    def add_batch_record(self, table_id: str, fields: list[dict]):
        """
        :param table_id:
        :param fields: [{"立项名称": "xxx"}]
        :return:
        """
        try:
            url = f'https://open.feishu.cn/open-apis/bitable/v1/apps/{self.app_token}/tables/{table_id}/records/batch_create'
            records = [{'fields': field} for field in fields]
            # print("插入数据", json.dumps(records))
            payload = json.dumps({
                "records": records
            })
            response = requests.post(url, headers=self.headers, data=payload)
            if response.status_code != 200:
                logger.debug(f'add batch record fail: {response.text}, status code: {response.status_code}')
                return

            data = response.json()
            # logger.debug(f'record_fields : {records}')
            logger.debug(f'add batch record success: {data}')
            return data

        except Exception as e:
            logger.exception(e)

    def update_record(self, fields: dict, table_id: str, record_id: str):
        """
        :param fields: {字段名:内容, 字段名:内容}
        :param table_id: 表id
        :param record_id: 记录id
        { "多行文本": "多行文本内容",}
        :return:
        """
        try:
            url = f"https://open.feishu.cn/open-apis/bitable/v1/apps/{self.app_token}/tables/{table_id}/records/{record_id}"
            payload = json.dumps({
                "fields": fields
            })
            response = requests.request("PUT", url, headers=self.headers, data=payload)
            if response.status_code != 200:
                logger.error(f'update record fail: {response.text}, status code: {response.status_code}')
                return
            data = response.json()
            logger.debug(f'update record success: {data}')
            return data

        except Exception as e:
            logger.exception(e)

    def update_batch_record(self, table_id: str, record_data: list):
        """
        :param table_id:
        :param record_data: record_data-> [{'fields':{}, record_id:''}]
        """
        url = f"https://open.feishu.cn/open-apis/bitable/v1/apps/{self.app_token}/tables/{table_id}/records/batch_update"
        logger.error(url)
        payload = json.dumps({"records": record_data})
        response = requests.request("POST", url, headers=self.headers, data=payload)
        if response.status_code != 200:
            logger.error(f'update batch record fail: {response.text}, status code: {response.status_code}')
            return
        data = response.json()
        logger.debug(f'update batch record success: {data}')

    # 查询数据
    def get_batch_records(self, table_id: str, page_size: int = 500, view_id=None, filter_data=None, sort=None):
        try:
            # page_size 目前查询都是有过滤的 基本没超过400-500条
            url = f'https://open.feishu.cn/open-apis/bitable/v1/apps/{self.app_token}/tables/{table_id}/records/search?page_size={page_size}'
            payload = json.dumps({
                'automatic_fields': False,
                'view_id': view_id,
                'filter': filter_data,
                'sort': sort
            })
            response = requests.request("POST", url, headers=self.headers, data=payload)
            # print("+++++", response.text)
            if response.status_code != 200:
                logger.error(f'get batch record fail: {response.text}, status code: {response.status_code}')
                return

            data = response.json()
            # logger.debug(f'get batch record success: {data}')
            return data

        except Exception as e:
            logger.exception(e)

    def delete_batch_record(self, table_id: str, record_ids: list):
        """
        :param table_id:
        :param record_ids: ["recwNXzPQv"]
        :return:
        """
        url = f"https://open.feishu.cn/open-apis/bitable/v1/apps/{self.app_token}/tables/{table_id}/records/batch_delete"
        payload = json.dumps({"records": record_ids})
        response = requests.request("POST", url, headers=self.headers, data=payload)
        if response.status_code != 200:
            logger.error(f'delete batch record fail: {response.text}, status code: {response.status_code}')
            return

        data = response.json()
        logger.debug(f'delete batch record success: {data}')
        return data

    def view_record(self, table_id: str, view_id, view_name, record_id: str):
        url = f'https://open.feishu.cn/open-apis/bitable/v1/apps/{self.app_token}/tables/{table_id}/views/{view_id}'
        payload = json.dumps({
            "property": {
                "hierarchy_config": {
                    "field_id": "fldfASqam8"
                }
            },
            "view_name": view_name
        })

    def upload_image(self, image_path: str) -> str:
        """
        上传本地图片到飞书，返回图片key用于插入表格

        :param image_path: 本地图片文件路径
        :return: 飞书图片资源key
        """
        if not os.path.exists(image_path):
            raise FileNotFoundError(f"图片文件不存在: {image_path}")

        # 检查文件格式
        valid_extensions = ['.png', '.jpg', '.jpeg', '.gif', '.bmp']
        ext = os.path.splitext(image_path)[1].lower()
        if ext not in valid_extensions:
            raise ValueError(f"不支持的图片格式: {ext}，支持格式: {valid_extensions}")

        try:
            # 飞书图片上传API
            url = "https://open.feishu.cn/open-apis/im/v1/images"
            headers = {
                "Authorization": f"Bearer {self.get_tenant_access_token()}",
                # 注意：上传图片时Content-Type需要为multipart/form-data
            }

            # 读取图片文件
            with open(image_path, 'rb') as f:
                files = {
                    'image': (os.path.basename(image_path), f, f'image/{ext[1:]}')
                }
                response = requests.post(url, headers=headers, files=files)

            if response.status_code != 200:
                raise Exception(f"图片上传失败: {response.text}, 状态码: {response.status_code}")

            data = response.json()
            if data.get("code") != 0:
                raise Exception(f"图片上传失败: {data.get('msg')}")

            image_key = data.get("data", {}).get("image_key")
            if not image_key:
                raise Exception("上传成功但未返回image_key")

            self.logger.debug(f"图片上传成功: {image_path} -> image_key: {image_key}")
            return image_key

        except Exception as e:
            self.logger.error(f"图片上传失败: {str(e)}")
            raise

    def add_record_with_image(self, table_id: str, fields: dict, image_field_name: str, image_path: str) -> dict:
        """
        插入包含图片的记录

        :param table_id: 数据表ID
        :param fields: 其他字段字典 (不含图片字段)
        :param image_field_name: 表格中图片字段的名称
        :param image_path: 本地图片路径
        :return: 飞书API返回结果
        """
        try:
            # 1. 上传图片获取image_key
            image_key = self.upload_image(image_path)

            # 2. 构建包含图片的字段数据
            image_field_value = {
                "type": "image",
                "image_key": image_key,
                "name": os.path.basename(image_path)  # 图片显示名称
            }

            # 合并图片字段和其他字段
            record_fields = {**fields, image_field_name: image_field_value}

            # 3. 调用批量插入接口
            result = self.add_batch_record(table_id, [record_fields])
            return result

        except Exception as e:
            self.logger.error(f"插入带图片的记录失败: {str(e)}")
            raise

    def get_single_record_by_unique_field(self, table_id: str, field_name: str, field_value: list,
                                          page_size: int = 1) -> dict or None:
        """
        通过唯一字段查询单个记录（需确保字段值唯一，否则只返回第一条）
        :param table_id: 目标表格ID
        :param field_name: 唯一字段名（如 "ID号" "小红书主页链接"）
        :param field_value: 唯一字段值（如 "123456" "https://xiaohongshu.com/xxx"）
        :param page_size: 分页大小，默认为1（实际使用中会强制为1）
        :return: 匹配的单条记录字典（无匹配时返回 None）
        """
        if not (table_id and field_name and field_value is not None):
            self.logger.error("查询单个记录失败：table_id、field_name、field_value 不能为空")
            return None

        filter_data = {
            "conjunction": "and",
            "conditions": [
                {
                    "field_name": field_name,
                    "operator": "is",
                    "value": [str(field_value).strip()]  # 核心：单值→列表格式
                }
            ]
        }

        # 调用查询接口
        result = self.get_batch_records(
            table_id=table_id,
            filter_data=filter_data
        )

        # 解析结果
        if result and result.get("code") == 0:
            records = result.get("data", {}).get("items", [])
            if len(records) > 1:
                self.logger.warning(f"字段 {field_name} 的值 {field_value} 不唯一，返回第一条记录")
            return records[0] if records else None
        else:
            self.logger.error(f"通过字段查询失败：{result.get('msg', '未知错误')}" if result else "接口调用失败")
            return None

    def get_batch_records2(self, filter_data, table_id, page_size=1):
        try:
            # page_size 目前查询都是有过滤的 基本没超过400-500条
            url = f'https://open.feishu.cn/open-apis/bitable/v1/apps/{self.app_token}/tables/{table_id}/records/search?page_size={page_size}'
            payload = json.dumps({
                'automatic_fields': True,
                'filter': filter_data,
            })
            response = requests.request("POST", url, headers=self.headers, data=payload)
            # print("+++++", response.text)
            if response.status_code != 200:
                logger.error(f'get batch record fail: {response.text}, status code: {response.status_code}')
                return

            data = response.json()
            # logger.debug(f'get batch record success: {data}')
            return data

        except Exception as e:
            logger.exception(e)
